package com.javaweb.util.core;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.util.CollectionUtils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.util.DefaultIndenter;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.javaweb.constant.CommonConstant;
import com.javaweb.constant.PatternConstant;
import com.javaweb.enums.CamelCaseEnum;
import com.javaweb.enums.JsonTypeEnum;

import net.sf.json.JSONObject;

/**
 * 字符串工具类
 * 
 * @author tank2140896
 */
public final class StringUtil {
	
	/**
	 * 简单对象转字符串
	 * 
	 * @param obj 任何对象
	 * @return String 字符串
	 */
	public static String objectEasy2String(Object obj){
		if(obj==null){
			return CommonConstant.NULL_VALUE;
		}
		return String.valueOf(obj);
	}
	
	/**
	 * 去除前后指定字符
	 * <p>
	 * trim()方法的增强
	 * @param str 待处理的字符串
	 * @param c 需要去除的字符
	 * @return String 处理后字符串
	 */
	public static String stripTrim(String str,char c) {
		if(isEmpty(str)) {
			return str;
		}
        int start = 0;
        int end = str.length();
        while(start<end) {
        	if(str.charAt(start)==c) {
        		start++;
            }else {
                if(str.charAt(end-1)==c) {
                	end--;
                }else {
                    break;
                }
            }
        }
        return str.substring(start,end);
	}
	
	/**
	 * 处理字符串的null值
	 * @param str 字符串
	 * @return 非null字符串，如果字符串本身为null则返回空字符串
	 */
	public static String handleNullString(String str) {
		//return Optional.ofNullable(str).map(e->e.strip()).orElse(CommonConstant.EMPTY_VALUE);
		return str == null ? CommonConstant.EMPTY_VALUE : str.strip();
	}
	
	/**
	 * 判断字符串为空或null
	 * @param str 字符串
	 * @return boolean true：为空或null；false：不为空且不为null
	 */
	public static boolean isEmpty(String str) {
		return CommonConstant.EMPTY_VALUE.equals(handleNullString(str));
	}
	
	/**
	 * 判断是否含有中文字符
	 * @param str 字符串
	 * @return boolean true：含有中文字符；false：不含有中文字符
	 */
	public static boolean isContainChinese(String str){
		return str == null ? false : (str.length()==str.getBytes().length ? false : true);
	}
	
	/**
	 * 获取某个类的绝对路径
	 * @param cls 类
	 * @return String 某个类的绝对路径
	 */
	public static String getClassAbsolutePath(Class<?> cls){
		String filePath = cls.getProtectionDomain().getCodeSource().getLocation().getFile();
		//结果如下->/E:/code/gitee/JavaWeb/common/target/classes/
		return URLDecoder.decode(filePath,StandardCharsets.UTF_8);
	}
	
	/**
	 * 字符串替换
	 * @param template 模板字符串，如：just{{a}}test{{b}}
	 * @param data 模板里的映射字段，如：Map<String,String> data = new HashMap<>();data.put("a","123");data.put("b","456");
	 * @param regex 模板替换的正则表达式，如：\\{\\{(.+?)\\}\\}
	 * @return String 根据模板替换后的字符串
	 */
	public static String stringReplace(String template,Map<String,String> data,String regex){
		StringBuilder stringBuilder = new StringBuilder();
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(template);
        while(matcher.find()){
            String name = matcher.group(1);//键名
            String value = data.get(name);//键值
            if(value!=CommonConstant.NULL_VALUE){
            	matcher.appendReplacement(stringBuilder,value);
            }
        }
        matcher.appendTail(stringBuilder);
        return stringBuilder.toString();
	}
	
	/**
	 * 设置敏感词（简易实现）
	 * @param keyWordList 敏感词列表
	 * @return JSONObject 敏感词层次对象
	 */
	private static final String END_TAG_NAME = "isEnd";
	public static JSONObject setSensitiveWord(List<String> keyWordList) {
		JSONObject jo = new JSONObject();
		if(!CollectionUtils.isEmpty(keyWordList)) {
			Iterator<String> iterator = keyWordList.iterator();
			while(iterator.hasNext()) {
				JSONObject temp = jo;
				String each = iterator.next();
				for(int i=0;i<each.length();i++) {
					String str = String.valueOf(each.charAt(i));
					Object obj = temp.get(str);
					if(obj==null) {
						JSONObject joo = new JSONObject();
						joo.put(END_TAG_NAME,i==(each.length()-1)?true:false);
						temp.put(str,joo);
					}
					temp = (JSONObject)temp.get(str);//对象引用精髓所在
				}
			}
		}
		return jo;
	}
	
	/**
	 * 敏感词检查（简易实现）
	 * @param text 敏感词
	 * @param sensitiveWordRule 敏感词层次对象
	 * @see StringUtil#setSensitiveWord
	 * @return boolean true：是敏感词；false：不是敏感词
	 */
	public static boolean isContainSensitiveWord(String text,JSONObject sensitiveWordRule) {
		List<String> out = new ArrayList<>();
		for(int i=0;i<text.length();i++) {
			List<String> temp = new ArrayList<>();
			String each = String.valueOf(text.charAt(i));
			temp.add(each);
			JSONObject jo = sensitiveWordRule;
			while(true) {
				jo = (JSONObject)jo.get(each);
				if(jo!=null) {
					if(true==(boolean)jo.get(END_TAG_NAME)){
						out.add(String.join("",temp));
						temp.clear();
						return true;
					}else {
						i++;
						each = String.valueOf(text.charAt(i));
						temp.add(each);
					}
				}else {
					temp.clear();
					break;
				}
			}
		}
		//return out;
		return false;
	}
	
	/**
	 * 获取对象的JSON类型
	 * @param obj 对象
	 * @return JsonTypeEnum JSON类型
	 */
	public static JsonTypeEnum getJsonType(Object obj){
		JsonTypeEnum jsonTypeEnum = JsonTypeEnum.NULL;
		if(obj!=null) {
			if(obj instanceof String){
				jsonTypeEnum = JsonTypeEnum.STRING;
			}else{
				String str = obj.toString();
				if(str.startsWith("[")){
					jsonTypeEnum = JsonTypeEnum.ARRAY;
				}else if(str.startsWith("{")){
					jsonTypeEnum = JsonTypeEnum.OBJECT;
				}else if(CommonConstant.TRUE_STRING.equals(str)||CommonConstant.FALSE_STRING.equals(str)){
					jsonTypeEnum = JsonTypeEnum.BOOLEAN;
				}else if(PatternConstant.NUMBER_PATTERN.matcher(str).matches()){
					jsonTypeEnum = JsonTypeEnum.NUMBER;
				}
			}
		}
		return jsonTypeEnum;
	}
	
	/**
	 * 将JOSN格式化文本转化为一行字符串
	 * <P>
	 * 原文本：
	 * {
	 *     "userName":"张三",
	 * 	   "score":[1,2,3],
	 * 	   "face":{
	 * 	       "positionCount":"我b c",
	 * 		   "image":["x","y","z"]
	 * 		},
	 * 		"age":17
	 * }
	 * 转化后：
	 * {"userName":"张三","score":[1,2,3],"face":{"positionCount":"我b c","image":["x","y","z"]},"age":17}
	 * @param file json文件
	 * @param charset 字符集
	 * @return String 只有一行的JSON字符串
	 * @throws IOException IO流异常
	 */
	public static String jsonFormatFileToJosnString(File file,Charset charset) throws IOException {
		StringBuilder stringBuilder = new StringBuilder();
		try(LineNumberReader lineNumberReader = new LineNumberReader(new InputStreamReader(new FileInputStream(file),charset))){
			String eachLine = CommonConstant.NULL_VALUE;
			while((eachLine=lineNumberReader.readLine())!=CommonConstant.NULL_VALUE){
				if(StringUtil.isEmpty(eachLine)) {
					continue;
				}
				stringBuilder.append(eachLine.strip());
			}
		}catch (IOException e) {
			throw new IOException(e);
		}
		return stringBuilder.toString();
	}

	/**
	 * 将JOSN字符串格式化输出
	 * <p>
	 * 原字符串：
	 * {"userName":"张三","score":[1,2,3],"face":{"positionCount":"我b c","image":["x","y","z"]},"age":17}
	 * 转化后：
	 * {
	 *     "userName":"张三",
	 * 	   "score":[1,2,3],
	 * 	   "face":{
	 * 	       "positionCount":"我b c",
	 * 		   "image":["x","y","z"]
	 * 		},
	 * 		"age":17
	 * }
	 * @param obj JSON对象（不能是字符串）
	 * @return String 格式化后的JSON字符串
	 */
	public static String jsonStringToJsonFormatForAlibaba(Object obj) throws Exception {
		ObjectMapper mapper = new ObjectMapper();
		DefaultPrettyPrinter.Indenter indenter = new DefaultIndenter("  ", DefaultIndenter.SYS_LF);
        DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
        printer.indentObjectsWith(indenter);
        printer.indentArraysWith(indenter);
        return mapper.writer(printer).writeValueAsString(obj);
	}
	
	/**
	 * 将包含日期的对象转成JSON字符串
	 * @param object 包含日期的对象
	 * @param datePattern 日期正则
	 * @return String 转化后的JSON字符串
	 * @throws JsonProcessingException JSON转化异常
	 */
	public static String withDate2JsonString(Object object,String datePattern) throws JsonProcessingException {
		ObjectMapper objectMapper = new ObjectMapper();
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern/*"yyyy-MM-dd HH:mm:ss"*/);
		objectMapper.setDateFormat(simpleDateFormat);
		return objectMapper.writeValueAsString(object);
	}
	
	/**
	 * 驼峰转化
	 * @param str 待驼峰转化的字符串
	 * @param camelCaseEnum CamelCaseEnum
	 * @return String 驼峰转化后字符串
	 */
	public static String camelCaseConvert(String str,CamelCaseEnum camelCaseEnum){
		if(isEmpty(str)) {
			return str;
		}
		str = str.strip().replaceAll(CommonConstant.BAR,CommonConstant.UNDERLINE);//将-替换为_
		String strs[] = str.split(CommonConstant.UNDERLINE);//分割_
		StringBuilder stringBuilder = new StringBuilder();
		for(int i=0;i<strs.length;i++){
			if(i==0){
				if(camelCaseEnum==CamelCaseEnum.FIRST_WORD_LOWER){
					stringBuilder.append(strs[i].substring(0,1).toLowerCase()).append(strs[i].substring(1,strs[i].length()));
				}else if(camelCaseEnum==CamelCaseEnum.FIRST_WORD_UPPER){
					stringBuilder.append(strs[i].substring(0,1).toUpperCase()).append(strs[i].substring(1,strs[i].length()));
				}
			}else{
				stringBuilder.append(strs[i].substring(0,1).toUpperCase()).append(strs[i].substring(1,strs[i].length()));
			}
		}
		return stringBuilder.toString();
	}
	
}
